package com.chart.web.controller.chart;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.chart.chart.domian.*;
import com.chart.chart.domian.ChartConfigsAndViewsVo;
import com.chart.chart.domian.vo.*;
import com.chart.chart.service.*;
import com.chart.common.constant.CacheConstants;
import com.chart.common.constant.WeChatConstants;
import com.chart.common.core.controller.BaseController;
import com.chart.common.core.domain.AjaxResult;
import com.chart.common.core.domain.entity.SysUser;
import com.chart.common.core.domain.model.LoginUser;
import com.chart.common.core.page.TableDataInfo;
import com.chart.common.core.redis.RedisCache;
import com.chart.common.utils.ColorUtils;
import com.chart.common.utils.SecurityUtils;
import com.chart.framework.web.service.TokenService;
import com.chart.system.service.ISysUserService;
import com.chart.system.service.IUserCoinLogsService;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.chart.common.constant.CacheConstants.CHART_INTERFACE;
import static com.chart.common.constant.CacheConstants.CHART_THEME;
import static com.chart.common.constant.HttpStatus.CUSTOM_ERROR;


/**
 * 图表
 *
 * @author chart
 */
@RestController
@RequestMapping("/chart")
public class ChartController extends BaseController {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IChartConfigsService chartConfigsService;

    @Autowired
    private IChartConfigsInterfaceService chartConfigsInterfaceService;


    @Autowired
    private IChartConfigsUserService chartConfigsUserService;

    @Autowired
    private IChartThemeService chartThemeService;


    @Autowired
    private IChartTypeService chartTypeService;

    @Autowired
    private IChartTechnologyService chartTechnologyService;

    @Autowired
    private IChartSubjectTypeService chartSubjectTypeService;

    @Autowired
    private IChartViewsUserService chartViewsUserService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private IChartStatisticsService statisticsService;


    @Autowired
    private IChartThemeService themeService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private IUserCoinLogsService userCoinLogsService;

    // 令牌有效期（默认30分钟）
    @Value("${token.expireTime}")
    private int expireTime;


    @ApiOperation("技术领域信息")
    @GetMapping("/technology/info")
    @Transactional
    public AjaxResult technologyInfo(ChartTechnology chartTechnology) {
        ChartTechnology technology = chartTechnologyService.getOne(new LambdaQueryWrapper<ChartTechnology>().eq(ChartTechnology::getId, chartTechnology.getId()));
        if (technology.getParentId() != 0) {
            ChartTechnology list1 = chartTechnologyService.getOne(new LambdaQueryWrapper<ChartTechnology>().eq(ChartTechnology::getId, technology.getParentId()));
            list1.setSubset(technology);
            return AjaxResult.success(list1);
        }
        return AjaxResult.error();
    }

    @ApiOperation("技术领域列表")
    @GetMapping("/technology/list")
    @Transactional
    public AjaxResult technologyList(ChartTechnology chartTechnology) {
        List<ChartTechnology> list = redisCache.getCacheObject(CacheConstants.CHART_TECHNOLOGY);

        return AjaxResult.success(list);
    }

    @ApiOperation("技术领域列表")
    @GetMapping("/subjectType/list")
    @Transactional
    public AjaxResult V2technologyList(ChartSubjectType chartSubjectType) {
        List<ChartSubjectType> list = redisCache.getCacheObject(CacheConstants.CHART_SUBJECT_TYPE);
        return AjaxResult.success(list);
    }


    @ApiOperation("我的生成：列表(图表和大屏)")
    @GetMapping("/all/list")
    @Transactional
    public TableDataInfo allList(ChartConfigsUser configsUser) {
        configsUser.setUserId(SecurityUtils.getUserId());
        List<ChartConfigsAndViewsVo> ccav = chartConfigsUserService.getChartsAndViews(configsUser);
        return getDataTable(ccav);
    }

    @ApiOperation("图表渐变主题列表plus")
    @GetMapping("/theme/getGradientPlus")
    public AjaxResult getGradientPlus(Integer[] colorNums) {
//        List<ChartTheme> chartThemes = themeService.list(new LambdaQueryWrapper<ChartTheme>().orderByAsc(ChartTheme::getThemeType).orderByAsc(ChartTheme::getSort));
        List<List<ChartTheme>> newList = new ArrayList<>();
        for (Integer colorNum : colorNums) {
            List<ChartTheme> chartThemes = redisCache.getCacheObject(CHART_THEME);

            for (int i1 = 0; i1 < chartThemes.size(); i1++) {
                ChartTheme chartTheme = chartThemes.get(i1);
                String themeValue = chartTheme.getThemeValue();
                JSONObject jsonObject = JSONObject.parseObject(themeValue);
                List<String> colors = (List<String>) jsonObject.get("color");
                //判断数据是否已经超出了预设主题配色
                if (colorNum > colors.size()) {
                    //根据主题颜色获取过渡色
                    List<String> gradientColors = ColorUtils.generateGradientColors(colors, colorNum);
                    jsonObject.put("color", gradientColors);
                    chartTheme.setThemeValue(JSONObject.toJSONString(jsonObject));
                }
            }
            newList.add(chartThemes);
        }
        return AjaxResult.success(newList);
    }

    @ApiOperation("图表渐变主题列表p")
    @GetMapping("/theme/getGradients")
    public AjaxResult themeList(Integer colorNum) {
//        List<ChartTheme> chartThemes = themeService.list(new LambdaQueryWrapper<ChartTheme>().orderByAsc(ChartTheme::getThemeType).orderByAsc(ChartTheme::getSort));
        List<ChartTheme> chartThemes = redisCache.getCacheObject(CHART_THEME);
        for (int i = 0; i < chartThemes.size(); i++) {
            ChartTheme chartTheme = chartThemes.get(i);
            String themeValue = chartTheme.getThemeValue();
            JSONObject jsonObject = JSONObject.parseObject(themeValue);
            List<String> colors = (List<String>) jsonObject.get("color");
            //判断数据是否已经超出了预设主题配色
            if (colorNum > colors.size()) {
                //根据主题颜色获取过渡色
                List<String> gradientColors = ColorUtils.generateGradientColors(colors, colorNum);
                jsonObject.put("color", gradientColors);
                chartTheme.setThemeValue(JSONObject.toJSONString(jsonObject));
            }
        }
        return AjaxResult.success(chartThemes);
    }

    /**
     * 只返回一条数据
     *
     * @param id
     * @return
     */
    @ApiOperation("图表渐变主题列表p")
    @GetMapping("/theme")
    public AjaxResult theme(String themeName, Integer colorNum) throws Exception {
        if (themeName == null || colorNum == null) {
            return AjaxResult.error("themeName 或 colorNum为空");
        }
        LambdaQueryWrapper<ChartTheme> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChartTheme::getThemeName, themeName);
        List<ChartTheme> list = chartThemeService.list(wrapper);
        ChartTheme chartThem = list.get(0);

        if (chartThem == null) {
            return AjaxResult.error("Chart theme not found");
        }
        String themeValue = chartThem.getThemeValue();
        ObjectNode jsonNodes = ColorUtils.processChartColorsHert(themeValue, colorNum);
        return AjaxResult.success(jsonNodes);
    }


    @ApiOperation("图表渐变主题列表")
    @GetMapping("/theme/getGradientList")
    public AjaxResult themeList(Integer colorNum, Long themeId) {
        ChartTheme chartTheme = redisCache.getCacheObject(CHART_THEME + themeId);
        String themeValue = chartTheme.getThemeValue();
        JSONObject jsonObject = JSONObject.parseObject(themeValue);
        List<String> colors = (List<String>) jsonObject.get("color");
        if (colorNum > colors.size()) {
            List<String> gradientColors = ColorUtils.generateGradientColors(colors, colorNum);
            jsonObject.put("color", gradientColors);
            chartTheme.setThemeValue(JSONObject.toJSONString(jsonObject));
        }
        return AjaxResult.success(chartTheme);
    }


    @ApiOperation("图表主题列表")
    @GetMapping("/theme/list")
    @Transactional
    public AjaxResult themeList(ChartTheme chartTheme) {
        List<ChartTheme> list = null;
        if (ObjectUtils.isEmpty(chartTheme.getThemeType())) {
            list = redisCache.getCacheObject(CHART_THEME);
        } else {
            list = redisCache.getCacheObject(CHART_THEME + chartTheme.getThemeType());
        }
//        List<ChartTheme> list = chartThemeService.list(new LambdaQueryWrapper<ChartTheme>().orderByAsc(ChartTheme::getSort));
        return AjaxResult.success(list);
    }


    @GetMapping("list/test")
    public AjaxResult Ttest() {
        List<ChartConfigs> list = chartConfigsService.list();
        ChartConfigs configs = list.get(0);
        System.out.println("我是其中的一次" + configs);
        return AjaxResult.success(configs);
    }


   /* 之前的不要删除  @ApiOperation("图表详情")
    @GetMapping("/config/info")
    @Transactional
    public AjaxResult configInfo(ChartConfigs chartConfigs) {

        // 根据ID获取ChartConfigs对象
        ChartConfigs configs = chartConfigsService.getById(chartConfigs.getId()); //46
        if (configs == null) {
            return AjaxResult.error("未找到相关图表配置");
        }
        // 根据config_id获取ChartConfigsInterface对象列表
        List<ChartConfigsInterface> configInterfaces = chartConfigsInterfaceService.list( //46
                new LambdaQueryWrapper<ChartConfigsInterface>()
                        .eq(ChartConfigsInterface::getConfigId, chartConfigs.getId())
        );
        if (configInterfaces.isEmpty()) {
            return AjaxResult.error("未找到相关图表配置接口");
        }
        ChartConfigsInterface chartConfigsInterface = configInterfaces.get(0);
        String configAddr = chartConfigsInterface.getConfigAddr();




        // 根据configAddr查询所有具有相同configAddr的ChartConfigsInterface记录
        List<ChartConfigsInterface> sameAddrInterfaces = chartConfigsInterfaceService.list(
                new LambdaQueryWrapper<ChartConfigsInterface>()
                        .eq(ChartConfigsInterface::getConfigAddr, configAddr)
                        .eq(ChartConfigsInterface::getStatus, 0)
        );

        // 更新sameAddrInterfaces中的每个元素，设置chartTypeId、configName和status
        for (ChartConfigsInterface sameAddrInterface : sameAddrInterfaces) { //2
            Long configId = sameAddrInterface.getConfigId();
            ChartConfigs config = chartConfigsService.getById(configId);
            if (config != null) {
                Long chartTypeId = config.getChartTypeId();
                sameAddrInterface.setChartTypeId(String.valueOf(chartTypeId));  // 假设chartTypeId是Long类型，转换为String
                sameAddrInterface.setConfigName(config.getConfigName());  // 设置configName
            }
        }

        // 设置更新后的sameAddrInterfaces到configs中
        configs.setSameAddrInterfaces(sameAddrInterfaces);
        return AjaxResult.success(configs);
    }*/



    @ApiOperation("图表详情")
    @GetMapping("/config/info")
    @Transactional
    public AjaxResult configInfo(ChartConfigs chartConfigs) {

        // 根据传入的ID查询ChartConfigsInterface记录
        ChartConfigsInterface interfaceRecord = chartConfigsInterfaceService.getById(chartConfigs.getId());

        // 如果传入的ID对应的记录存在，且status为1，返回空的sameAddrInterfaces
        if (interfaceRecord != null && interfaceRecord.getStatus() == 1) {
            // 获取对应的ChartConfigs对象
            ChartConfigs configs = chartConfigsService.getById(interfaceRecord.getConfigId());
            if (configs == null) {
                return AjaxResult.error("未找到相关图表配置");
            }
            configs.setSameAddrInterfaces(Collections.emptyList());  // 设置sameAddrInterfaces为空数组
            return AjaxResult.success(configs);
        }

        // 根据ID获取ChartConfigs对象
        ChartConfigs configs = chartConfigsService.getById(chartConfigs.getId());
        if (configs == null) {
            return AjaxResult.error("未找到相关图表配置");
        }

        // 根据config_id获取ChartConfigsInterface对象列表
        List<ChartConfigsInterface> configInterfaces = chartConfigsInterfaceService.list(
                new LambdaQueryWrapper<ChartConfigsInterface>()
                        .eq(ChartConfigsInterface::getConfigId, chartConfigs.getId())
        );
        if (configInterfaces.isEmpty()) {
            return AjaxResult.error("未找到相关图表配置接口");
        }

        ChartConfigsInterface chartConfigsInterface = configInterfaces.get(0);
        String configAddr = chartConfigsInterface.getConfigAddr();

        // 根据configAddr查询所有具有相同configAddr且status=0的ChartConfigsInterface记录
        List<ChartConfigsInterface> sameAddrInterfaces = chartConfigsInterfaceService.list(
                new LambdaQueryWrapper<ChartConfigsInterface>()
                        .eq(ChartConfigsInterface::getConfigAddr, configAddr)
                        .eq(ChartConfigsInterface::getStatus, 0)
        );

        // 更新sameAddrInterfaces中的每个元素，设置chartTypeId和configName
        for (ChartConfigsInterface sameAddrInterface : sameAddrInterfaces) {
            Long configId = sameAddrInterface.getConfigId();
            ChartConfigs config = chartConfigsService.getById(configId);
            if (config != null) {
                Long chartTypeId = config.getChartTypeId();
                sameAddrInterface.setChartTypeId(String.valueOf(chartTypeId));  // 假设chartTypeId是Long类型，转换为String
                sameAddrInterface.setConfigName(config.getConfigName());        // 设置configName
            }
        }
        // 设置更新后的sameAddrInterfaces到configs中
        configs.setSameAddrInterfaces(sameAddrInterfaces);
        return AjaxResult.success(configs);
    }















//    @ApiOperation("图表详情")
//    @GetMapping("/config/info")
//    @Transactional
//    public AjaxResult configInfo(
//            @RequestParam Long chartConfigsId,
//            @RequestParam(required = false) Long interfaceId) {
//
//        // 根据ID获取ChartConfigs对象
//        ChartConfigs configs = chartConfigsService.getById(chartConfigsId);
//        if (configs == null) {
//            return AjaxResult.error("未找到相关图表配置");
//        }
//
//        // 如果传入了interfaceId，检查其状态
//        if (interfaceId != null) {
//            ChartConfigsInterface interfaceRecord = chartConfigsInterfaceService.getById(interfaceId);
//            if (interfaceRecord != null
//                    && interfaceRecord.getStatus() == 1
//                    && interfaceRecord.getConfigId().equals(chartConfigsId)) {
//                // 当传入的interfaceId存在且status=1，设置sameAddrInterfaces为空数组
//                configs.setSameAddrInterfaces(Collections.emptyList());
//                return AjaxResult.success(configs);
//            }
//        }
//
//        // 根据config_id获取ChartConfigsInterface对象列表
//        List<ChartConfigsInterface> configInterfaces = chartConfigsInterfaceService.list(
//                new LambdaQueryWrapper<ChartConfigsInterface>()
//                        .eq(ChartConfigsInterface::getConfigId, chartConfigsId)
//        );
//
//        if (configInterfaces.isEmpty()) {
//            return AjaxResult.error("未找到相关图表配置接口");
//        }
//
//        // 获取第一个ChartConfigsInterface
//        ChartConfigsInterface chartConfigsInterface = configInterfaces.get(0);
//        String configAddr = chartConfigsInterface.getConfigAddr();
//
//        // 根据configAddr查询所有具有相同configAddr且status=0的ChartConfigsInterface记录
//        List<ChartConfigsInterface> sameAddrInterfaces = chartConfigsInterfaceService.list(
//                new LambdaQueryWrapper<ChartConfigsInterface>()
//                        .eq(ChartConfigsInterface::getConfigAddr, configAddr)
//                        .eq(ChartConfigsInterface::getStatus, 0)
//        );
//
//        // 更新sameAddrInterfaces中的每个元素，设置chartTypeId和configName
//        for (ChartConfigsInterface sameAddrInterface : sameAddrInterfaces) {
//            Long configId = sameAddrInterface.getConfigId();
//            ChartConfigs config = chartConfigsService.getById(configId);
//            if (config != null) {
//                Long chartTypeId = config.getChartTypeId();
//                sameAddrInterface.setChartTypeId(String.valueOf(chartTypeId));  // 假设chartTypeId是Long类型，转换为String
//                sameAddrInterface.setConfigName(config.getConfigName());        // 设置configName
//            }
//        }
//
//        // 设置更新后的sameAddrInterfaces到configs中
//        configs.setSameAddrInterfaces(sameAddrInterfaces);
//        return AjaxResult.success(configs);
//    }









    /**
     * 专家图例切图返回相关类型的接口
     *
     * @param chartConfigsUser
     * @return
     */
    @ApiOperation("图表详情")
    @GetMapping("expert/config/info")
    @Transactional
    public AjaxResult expertConfigInfo(ChartConfigsUser chartConfigsUser) {
        //非空效验
        if (chartConfigsUser.getConfigId() == null) {
            return AjaxResult.error("configId不能为空");
        }
        LambdaQueryWrapper<ChartConfigsUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ChartConfigsUser::getConfigId, chartConfigsUser.getConfigId());
        lqw.eq(ChartConfigsUser::getUserId, 2);//user
        lqw.eq(ChartConfigsUser::getStatus, 0);
        // 返回查询结果
        List<ChartConfigsUser> list = chartConfigsUserService.list(lqw);
        list.stream().forEach(item -> {
            item.setChartData(null);
            Long configId = item.getConfigId();
            ChartConfigs configs = chartConfigsService.getById(configId);
            ChartConfigsInterface chartConfigsInterface = chartConfigsInterfaceService.getById(configId);
            ChartConfigs config = chartConfigsService.getById(configId);
            String configAddr = chartConfigsInterface.getConfigAddr();
            item.setConfigAddr(configAddr);
            item.setChartTypeId(String.valueOf(config.getChartTypeId()));
            item.setConfigName(config.getConfigName());
            item.setConfigText(configs.getConfigText());
            item.setWindowText(config.getWindowText());
            item.setChartCover(null);// 设置configName
        });
        return AjaxResult.success(list);
    }


    @ApiOperation("图表列表")
    @GetMapping("/config/list")
    @Transactional
    public AjaxResult configList() {
        ChartsVo chartsVo = new ChartsVo();
        ArrayList<ChartMenuVo> chartMenuVos = new ArrayList<>();
        ArrayList<ChartListVo> chartListVos = new ArrayList<>();
        for (int i = 0; i < 2; i++) {
            ChartMenuVo chartMenuVo = new ChartMenuVo();
            if (i == 0) {
                chartMenuVo.setLabel("通用模版");
                List<ChartType> list = chartTypeService.list(new LambdaQueryWrapper<ChartType>().ne(ChartType::getId, 15).ne(ChartType::getStatus, 1).orderByAsc(ChartType::getSort));
                for (int i1 = 0; i1 < list.size(); i1++) {
                    ChartType chartType = list.get(i1);
//                    List<ChartConfigs> list1 = chartConfigsService.list(new LambdaQueryWrapper<ChartConfigs>().eq(ChartConfigs::getChartTypeId, chartType.getId()));
                    //根据类型获取图表配置信息
                    List<ChartConfigs> list1 = chartConfigsService.getBriefList(chartType.getId());
                    ChartListVo chartListVo = new ChartListVo();
                    chartListVo.setLabel(chartType.getName());
                    chartListVo.setList(list1);

                    chartListVos.add(chartListVo);
                }
                chartMenuVo.setChildren(list);
            } else {
                chartMenuVo.setLabel("专家模版");
                List<ChartType> list = chartTypeService.list(new LambdaQueryWrapper<ChartType>().eq(ChartType::getId, 15).ne(ChartType::getStatus, 1));
                for (int i1 = 0; i1 < list.size(); i1++) {
                    ChartType chartType = list.get(i1);
//                    List<ChartConfigs> list1 = chartConfigsService.list(new LambdaQueryWrapper<ChartConfigs>().eq(ChartConfigs::getChartTypeId, chartType.getId()));
                    List<ChartConfigs> list1 = chartConfigsService.getBriefList(chartType.getId());
                    ChartListVo chartListVo = new ChartListVo();
                    chartListVo.setLabel(chartType.getName());
                    chartListVo.setList(list1);
                    chartListVos.add(chartListVo);
                }
                chartMenuVo.setChildren(list);
            }
            chartMenuVos.add(chartMenuVo);
        }
        chartsVo.setMenuList(chartMenuVos);
        chartsVo.setChartsList(chartListVos);
        return AjaxResult.success(chartsVo);
    }


    @ApiOperation("图表列表")
    @GetMapping("/config/v2/list")
    @Transactional
    public AjaxResult v3configList(@RequestParam("userId") Long userId) {
        ChartsVo chartsVo = new ChartsVo();
        ArrayList<ChartMenuVo> chartMenuVos = new ArrayList<>();
        ArrayList<ChartListVo> chartListVos = new ArrayList<>();
        for (int i = 0; i < 2; i++) {
            ChartMenuVo chartMenuVo = new ChartMenuVo();
            if (i == 0) {
                chartMenuVo.setLabel("通用模版");
                List<ChartType> list = chartTypeService.list(new LambdaQueryWrapper<ChartType>()
                        .ne(ChartType::getId, 15)
                        .ne(ChartType::getStatus, 1)
                        .orderByAsc(ChartType::getSort));


                for (ChartType chartType : list) {
                    List<ChartConfigs> list1 = chartConfigsService.getBriefListByUserId(chartType.getId(), userId);
                    ChartListVo chartListVo = new ChartListVo();
                    chartListVo.setLabel(chartType.getName());
                    chartListVo.setList(list1);
                    chartListVos.add(chartListVo);
                }
                chartMenuVo.setChildren(list);


            } else {
                chartMenuVo.setLabel("专家模版");
                List<ChartType> list = chartTypeService.list(new LambdaQueryWrapper<ChartType>()
                        .eq(ChartType::getId, 15)
                        .ne(ChartType::getStatus, 1));
                for (ChartType chartType : list) {
                    List<ChartConfigs> list1 = chartConfigsService.getBriefListByUserId(chartType.getId(), userId);
                    ChartListVo chartListVo = new ChartListVo();
                    chartListVo.setLabel(chartType.getName());
                    chartListVo.setList(list1);
                    chartListVos.add(chartListVo);
                }
                chartMenuVo.setChildren(list);
            }
            chartMenuVos.add(chartMenuVo);
        }
        chartsVo.setMenuList(chartMenuVos);
        chartsVo.setChartsList(chartListVos);
        return AjaxResult.success(chartsVo);
    }


    //  图表名称重复 returnedValued= 1。然后接收前端的  returnedValued字段 如何 returnedValued=0增加操作。returnedValued=2更新操作。

    /*
    *
    private Integer coins;
    private Date registrationRewardTime;
    private Date completeInfoRewardTime;
    private Date dailyLoginRewardTime;
    *
    * */

    /**
     *
     *

     */
    /**
     * 0：新增操作
     * 1：图表名称重复
     * 2：更新操作returnValue 第一次不传值  第二次传值    0：新增操作   2：更新操作
     * 7.18 可以用的
     *
     * @param configsUser
     * @return
     */



/*    @ApiOperation("我的生成：新增")
    @PostMapping("/user/add")
    @Transactional
    public AjaxResult addOrUpdate(@RequestBody ChartConfigsUser configsUser) {
        if (ObjectUtils.isEmpty(configsUser.getChartName())) {
            return AjaxResult.error("请填写图表名称");
        }
        List<ChartConfigsUser> users = null;
        if (ObjectUtils.isEmpty(configsUser.getFileId())) {
            users = chartConfigsUserService.list(new LambdaQueryWrapper<ChartConfigsUser>()
                    .eq(ChartConfigsUser::getChartName, configsUser.getChartName())
                    .eq(ChartConfigsUser::getUserId, SecurityUtils.getUserId())
                    .isNull(ChartConfigsUser::getFileId));
        } else {
            users = chartConfigsUserService.list(new LambdaQueryWrapper<ChartConfigsUser>()
                    .eq(ChartConfigsUser::getChartName, configsUser.getChartName())
                    .eq(ChartConfigsUser::getUserId, SecurityUtils.getUserId())
                    .eq(ChartConfigsUser::getFileId, configsUser.getFileId()));
        }
        if (!users.isEmpty() && (configsUser.getReturnValue() == null || configsUser.getReturnValue() != 2)) {
            return AjaxResult.success("图表名称重复").put("returnValue", 1);
        }
        // 根据 returnValue 进行操作
        if (configsUser.getReturnValue() != null) {

            if (configsUser.getReturnValue() == 0) {
                // 新增操作
                configsUser.setStatus(0);
                configsUser.setUserId(SecurityUtils.getUserId());
                System.out.println(configsUser);
                chartConfigsUserService.save(configsUser);
                return AjaxResult.success("新增成功").put("returnValue", 0);

            } else if (configsUser.getReturnValue() == 2) {

                // 更新操作
                configsUser.setUserId(SecurityUtils.getUserId());
                // 首先尝试根据id更新对象
                if (configsUser.getId() != null && !configsUser.getId().equals("")) {
                    chartConfigsUserService.updateById(configsUser);
                } else {
                    // 如果id为null或空字符串，根据chartName查询对象
                    String chartName = configsUser.getChartName();
                    Long userId = configsUser.getUserId();
                    System.out.println(chartName+userId);
                    if (chartName != null && !chartName.isEmpty()) {
                        // 这里假设有一个方法可以按照chartName查询对象
                        ChartConfigsUser existingUser = chartConfigsUserService.getOneByChartName(chartName,SecurityUtils.getUserId());


                        if (existingUser != null) {
                            // 如果查询到对象，则更新对象的id并执行更新操作
                            configsUser.setId(existingUser.getId());
                            chartConfigsUserService.updateById(configsUser);
                        }
                    }
                }}
                return AjaxResult.success("更新成功").put("returnValue", 2);
        }
        return AjaxResult.error("无效的操作");
    }*/

/*
    @Value("${file.upload-dir}")
    private String uploadDir;*/

/*    @ApiOperation("我的生成：新增测试")
    @PostMapping("/add/textqq")
    @Transactional
    public AjaxResult addOrUpdateTextOne(@RequestBody ChartConfigsUser configsUser) throws UnsupportedEncodingException {
        String chartCover = configsUser.getChartCover();
        // 去除 Base64 前缀
        if (chartCover != null && chartCover.startsWith("data:image/png;base64,")) {
            chartCover = chartCover.substring("data:image/png;base64,".length());
        }
        // 检查并解码 base64 字符串
        byte[] decodedBytes;
        try {
            decodedBytes = Base64.getDecoder().decode(chartCover);
        } catch (IllegalArgumentException e) {
            return AjaxResult.error("Base64编码无效: " + e.getMessage());
        }

        int randomInt = RandomUtils.nextInt(0, 100000);
        String fileName = "chartCover" + randomInt + ".png";
        File file = new File(uploadDir, fileName);

        // 确保上传目录存在
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        // 将字节数组写入文件
        try (FileOutputStream fos = new FileOutputStream(file)) {
            fos.write(decodedBytes);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("文件保存失败: " + e.getMessage());
        }

        // 读取文件并转换为Base64
        byte[] fileBytes;
        try (InputStream is = new FileInputStream(file)) {
            fileBytes = IOUtils.toByteArray(is);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("读取文件失败: " + e.getMessage());
        }
        String base64Encoded = Base64.getEncoder().encodeToString(fileBytes);

        // 返回Base64编码的图片字符串
        HashMap<Object, Object> map = new HashMap<>();
        map.put("base64", base64Encoded);

        return AjaxResult.success(map);
    }*/

/*    @RequestMapping("download")
    public void download(@Param("source") String source, HttpServletRequest request, HttpServletResponse response) throws Exception {
        File file = new File(source);
        if (file == null || !file.exists()) {
            throw new FileNotFoundException("请求的文件不存在");
        }
        OutputStream out = null;
        try {
            response.reset();
            response.setContentType("application/octet-stream; charset=utf-8");
            String agent = (String) request.getHeader("USER-AGENT");
            String fileName = file.getName();
            if (agent != null && agent.indexOf("MSIE") == -1) {
                // FF
                String enableFileName = "=?UTF-8?B?" + (new String(Base64.getEncoder().encode(fileName.getBytes("UTF-8")))) + "?=";
                response.setHeader("Content-Disposition", "attachment; filename=" + enableFileName);
            } else {
                // IE
                String enableFileName = new String(fileName.getBytes("GBK"), "ISO-8859-1");
                response.setHeader("Content-Disposition", "attachment; filename=" + enableFileName);
            }
            out = response.getOutputStream();
            out.write(org.apache.commons.io.FileUtils.readFileToByteArray(file));
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }*/

    //String uploadDir= " C:\\Users\\Administrator\\Desktop\\upload";
/*
    @PostMapping("upload")
    public String upload(HttpServletRequest request, HttpServletResponse response, MultipartFile upload) throws IllegalStateException, IOException, IOException {
        String realPath = "E:/fj";
        // 判断文件是否为空
        if (!upload.isEmpty()) {


            // 文件保存路径
            // 转存文件
            FileUtils.createDirectory(realPath);
            String name = upload.getOriginalFilename(); //得到上传文件名称
            String filePath = realPath +"/"+  name;  //真实的路径＋名称
            File newFile = FileUtils.getAvailableFile(filePath,0);//获取可以创建的文件名（如果有同名文件存在，参照Windows系统重命名为xxx(2).xxx)
            upload.transferTo(newFile);
            String absolutePath = newFile.getAbsolutePath();
            String suffix = absolutePath.substring(absolutePath.lastIndexOf("."));
            // return "http://202.75.216.132:9999/file/download?source=" + realPath + "/" + newFile.getName();
            return "http://yw.zjscxyj.com:8787/file/download?source=" + realPath + "/" + newFile.getName();


        }
        return "";
    }*/
    @ApiOperation("我的生成：新增测试")
    @PostMapping("/add/textqq")
    @Transactional
    public AjaxResult addOrUpdateTextOne(@RequestBody ChartConfigsUser configsUser) throws UnsupportedEncodingException {
        String chartCover = configsUser.getChartCover();
        // 去除 Base64 前缀
        if (chartCover != null && chartCover.startsWith("data:image/png;base64,")) {
            chartCover = chartCover.substring("data:image/png;base64,".length());
        }

        // 检查并解码 base64 字符串
        byte[] decodedBytes;
        try {
            decodedBytes = Base64.getDecoder().decode(chartCover);
        } catch (IllegalArgumentException e) {
            return AjaxResult.error("Base64编码无效: " + e.getMessage());
        }

        // 从配置文件中读取路径
        String uploadDir = "C:/Users/Administrator/Desktop/upload"; // 确保从配置中读取

        int randomInt = RandomUtils.nextInt(0, 100000);
        String fileName = "chartCover" + randomInt + ".png";
        File file = new File(uploadDir, fileName);

        // 确保上传目录存在
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }

        // 将字节数组写入文件
        try (FileOutputStream fos = new FileOutputStream(file)) {
            fos.write(decodedBytes);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("文件保存失败: " + e.getMessage());
        }

        // 获取文件的绝对路径
        String absolutePath = file.getAbsolutePath();

        // 构造访问 URL
        String url = "http://localhost:10003/file/download?source=" + absolutePath.replace("\\", "/");
        String fileRelativePath = file.getAbsolutePath().substring(uploadDir.length()).replace("\\", "/");
        // String fileRelativePath = file.getAbsolutePath().substring(uploadDir.length()).replace("\\", "/");

        System.out.println(fileName);
        HashMap<Object, Object> map = new HashMap<>();
        map.put("url", url);

        // 读取文件并转换为 Base64
        byte[] fileBytes;
        try (InputStream is = new FileInputStream(file)) {
            fileBytes = IOUtils.toByteArray(is);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("读取文件失败: " + e.getMessage());
        }

        String base64Encoded = "data:image/png;base64," + Base64.getEncoder().encodeToString(fileBytes);

        return AjaxResult.success(url);
    }



/*    @ApiOperation("我的生成：新增测试")
    @PostMapping("/add/textqq")
    @Transactional
    public AjaxResult addOrUpdateTextOne(@RequestBody ChartConfigsUser configsUser) throws UnsupportedEncodingException {
        String chartCover = configsUser.getChartCover();
        // 去除 Base64 前缀
        if (chartCover != null && chartCover.startsWith("data:image/png;base64,")) {
            chartCover = chartCover.substring("data:image/png;base64,".length());
        }
        // 检查并解码 base64 字符串
        byte[] decodedBytes;
        try {
            decodedBytes = Base64.getDecoder().decode(chartCover);
        } catch (IllegalArgumentException e) {
            return AjaxResult.error("Base64编码无效: " + e.getMessage());
        }
        int randomInt = RandomUtils.nextInt(0, 100000);
        String fileName = "chartCover" + randomInt + ".png";
        File file = new File(uploadDir, fileName);
        // 确保上传目录存在
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        // 将字节数组写入文件
        try (FileOutputStream fos = new FileOutputStream(file)) {
            fos.write(decodedBytes);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("文件保存失败: " + e.getMessage());
        }

        // 对路径进行URL编码
     //   String encodedPath = URLEncoder.encode(absolutePath, "UTF-8").replaceAll("\\+", "%20");

        // 构造访问 URL

       // fileRelativePath.replace("\\", "/")

        String url = "http://localhost:10003/file/download?source=" + ;

        HashMap<Object, Object> map = new HashMap<>();
        map.put("url",url);

        // 读取文件并转换为Base64
        byte[] fileBytes;
        try (InputStream is = new FileInputStream(file)) {
            fileBytes = IOUtils.toByteArray(is);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("读取文件失败: " + e.getMessage());
        }
        String base64Encoded = "data:image/png;base64," + Base64.getEncoder().encodeToString(fileBytes);

        return AjaxResult.success(url);
    }*/


    @RequestMapping("download")
    public void download(String source, HttpServletRequest request, HttpServletResponse response) throws Exception {
        File file = new File(source);
        if (file == null || !file.exists()) {
            throw new FileNotFoundException("请求的文件不存在");
        }
        OutputStream out = null;
        try {
            response.reset();
            response.setContentType("application/octet-stream; charset=utf-8");
            String agent = (String) request.getHeader("USER-AGENT");
            String fileName = file.getName();
            if (agent != null && agent.indexOf("MSIE") == -1) {
// FF
                String enableFileName = "=?UTF-8?B?" + (new String(Base64.getEncoder().encode(fileName.getBytes("UTF-8")))) + "?=";
                response.setHeader("Content-Disposition", "attachment; filename=" + enableFileName);
            } else {
// IE
                String enableFileName = new String(fileName.getBytes("GBK"), "ISO-8859-1");
                response.setHeader("Content-Disposition", "attachment; filename=" + enableFileName);
            }
//			response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
            out = response.getOutputStream();
            out.write(org.apache.commons.io.FileUtils.readFileToByteArray(file));
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    // base64
    @Value("${file.upload-dir}")
    private String uploadDir;

    @ApiOperation("我的生成：新增")
    @PostMapping("/user/add")
    @Transactional
    public AjaxResult addOrUpdate(@RequestBody ChartConfigsUser configsUser) throws UnsupportedEncodingException {


        Long userId = SecurityUtils.getUserId();
        SysUser sysUser = userService.queryById(userId);
        Integer isVip = sysUser.getIsVip();
        if (isVip == 0) { //不是VIP
            int seatCountNumber = userCoinLogsService.querySeatCount();//总席位数量// 查询席位的数量
            LambdaQueryWrapper<ChartConfigsUser> lqw = new LambdaQueryWrapper<>();
            lqw.eq(ChartConfigsUser::getUserId, userId);
            List<ChartConfigsUser> chartConfigsUsers = chartConfigsUserService.list(lqw);
            int size = chartConfigsUsers.size(); //已经使用的席位 //查询保存到我的生成的数量
            if (seatCountNumber <= size) {
                return AjaxResult.error(CUSTOM_ERROR, "保存文件数不足，请充值");
            }
        }

        if (ObjectUtils.isEmpty(configsUser.getChartName())) {
            return AjaxResult.error("请填写图表名称");
        }

        // String chartCover = configsUser.getChartCover();
        String chartCover = configsUser.getChartCover();
        // 去除 Base64 前缀
        if (chartCover != null && chartCover.startsWith("data:image/png;base64,")) {
            chartCover = chartCover.substring("data:image/png;base64,".length());
        }
        // 检查并解码 base64 字符串
        byte[] decodedBytes;
        try {
            decodedBytes = Base64.getDecoder().decode(chartCover);
        } catch (IllegalArgumentException e) {
            return AjaxResult.error("Base64编码无效: " + e.getMessage());
        }
        int randomInt = RandomUtils.nextInt(0, 100000);
        String fileName = "chartCover" + randomInt + ".png";
        String urlName = "/static/mychart/" + "chartCover" + randomInt + ".png";
        File file = new File(uploadDir, fileName);
        // 将字节数组写入文件
        try (FileOutputStream fos = new FileOutputStream(file)) {
            fos.write(decodedBytes);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("文件保存失败: " + e.getMessage());
        }

        String absolutePath = file.getAbsolutePath();
        String url7 = "http://localhost:10003/file/download?source=" + absolutePath.replace("\\", "/");
        String fileRelativePath = file.getAbsolutePath().substring(uploadDir.length()).replace("\\", "/");
        // 读取文件并转换为Base64
        byte[] fileBytes;
        try (InputStream is = new FileInputStream(file)) {
            fileBytes = IOUtils.toByteArray(is);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("读取文件失败: " + e.getMessage());
        }
        String base64Encoded = "data:image/png;base64," + Base64.getEncoder().encodeToString(fileBytes);
        List<ChartConfigsUser> users = null;
        if (ObjectUtils.isEmpty(configsUser.getFileId())) {
            users = chartConfigsUserService.list(new LambdaQueryWrapper<ChartConfigsUser>()
                    .eq(ChartConfigsUser::getChartName, configsUser.getChartName())
                    .eq(ChartConfigsUser::getUserId, userId)
                    .isNull(ChartConfigsUser::getFileId));
        } else {
            users = chartConfigsUserService.list(new LambdaQueryWrapper<ChartConfigsUser>()
                    .eq(ChartConfigsUser::getChartName, configsUser.getChartName())
                    .eq(ChartConfigsUser::getUserId, userId)
                    .eq(ChartConfigsUser::getFileId, configsUser.getFileId()));
        }
        if (!users.isEmpty() && (configsUser.getReturnValue() == null || configsUser.getReturnValue() != 2)) {
            return AjaxResult.success("图表名称重复").put("returnValue", 1);
        }
        // 根据 returnValue 进行操作
        if (configsUser.getReturnValue() != null) {
            if (configsUser.getReturnValue() == 0) {

                // 新增操作
                configsUser.setStatus(1);
                configsUser.setUserId(userId);
                configsUser.setImageUrl(urlName);
                configsUser.setImageBase64(base64Encoded);
                configsUser.setHot(0L);
                chartConfigsUserService.save(configsUser);
                return AjaxResult.success("新增成功").put("returnValue", 0).put("imageUrl", urlName).put("imageBase64", base64Encoded);
            } else if (configsUser.getReturnValue() == 2) {
                // 更新操作
                configsUser.setUserId(userId);
                configsUser.setImageUrl(urlName);
                configsUser.setImageBase64(base64Encoded);
                if (configsUser.getId() != null && !configsUser.getId().equals("")) {
                    chartConfigsUserService.updateById(configsUser);
                } else {
                    String chartName = configsUser.getChartName();
                    if (chartName != null && !chartName.isEmpty()) {
                        ChartConfigsUser existingUser = chartConfigsUserService.getOneByChartName(chartName, userId);
                        if (existingUser != null) {
                            configsUser.setId(existingUser.getId());
                            chartConfigsUserService.updateById(configsUser);
                        }
                    }
                }
                return AjaxResult.success("更新成功").put("returnValue", 2).put("imageUrl", urlName).put("imageBase64", base64Encoded);
            }
        }
        return AjaxResult.error("无效的操作");
    }






/*

    private void updateCache(Long userId, String chartName) {
        String key = "getInfoByName:" + userId + ":" + (chartName != null ? chartName : "all");
        List<ChartConfigsAndViewsVo> list = redisCache.getCacheList(key);

        if (list == null || list.isEmpty()) {
            list = new ArrayList<>();
            ChartConfigsAndViewsVo chartConfigsAndViewsVo = new ChartConfigsAndViewsVo();
            chartConfigsAndViewsVo.setUserId(userId);
            chartConfigsAndViewsVo.setName(chartName);

            if (!ObjectUtils.isEmpty(chartConfigsAndViewsVo.getFileId())) {
                List<ChartConfigsAndViewsVo> fileList = chartConfigsUserService.getFiles(chartConfigsAndViewsVo);
                if (fileList != null) {
                    list.addAll(fileList);
                }
                List<ChartConfigsAndViewsVo> cAvList = chartConfigsUserService.getChartsAndViewsBatch(chartConfigsAndViewsVo);
                if (cAvList != null) {
                    list.addAll(cAvList);
                }
            } else {
                list = chartConfigsUserService.getInfoByName(chartConfigsAndViewsVo);
                if (!ObjectUtils.isEmpty(list) && ObjectUtils.isEmpty(chartConfigsAndViewsVo.getName())) {
                    list = list.stream()
                            .filter(e -> ObjectUtils.isEmpty(e.getParentId()) || ObjectUtils.isEmpty(e.getFileId()))
                            .collect(Collectors.toList());
                }
            }

            if (!list.isEmpty()) {
                redisCache.setCacheListTwo(key, list, 10, TimeUnit.MINUTES);
            }
        }
    }*/


    /* if (ObjectUtils.isEmpty(configsUser.getChartName())) {
         return AjaxResult.error("请填写图表名称");
     }
     List<ChartConfigsUser> users = null;

     if (ObjectUtils.isEmpty(configsUser.getFileId())) {
         users = chartConfigsUserService.list(new LambdaQueryWrapper<ChartConfigsUser>()
                 .eq(ChartConfigsUser::getChartName, configsUser.getChartName())
                 .eq(ChartConfigsUser::getUserId, SecurityUtils.getUserId())
                 .isNull(ChartConfigsUser::getFileId));
     } else {
         users = chartConfigsUserService.list(new LambdaQueryWrapper<ChartConfigsUser>()
                 .eq(ChartConfigsUser::getChartName, configsUser.getChartName())
                 .eq(ChartConfigsUser::getUserId, SecurityUtils.getUserId())
                 .eq(ChartConfigsUser::getFileId, configsUser.getFileId()));
     }

     if (!users.isEmpty() && (configsUser.getReturnValue() == null || configsUser.getReturnValue() != 2)) {
         configsUser.setReturnValue(1);
         return AjaxResult.error("图表名称重复").put("returnValue", configsUser.getReturnValue());
     }

     // 根据 returnValue 进行操作
     if (configsUser.getReturnValue() != null) {
         if (configsUser.getReturnValue() == 0) {
             // 新增操作
             configsUser.setStatus(0);
             configsUser.setUserId(SecurityUtils.getUserId());
             chartConfigsUserService.save(configsUser);
             return AjaxResult.success("新增成功");
         } else if (configsUser.getReturnValue() == 2) {
             // 更新操作
             configsUser.setUserId(SecurityUtils.getUserId());
             chartConfigsUserService.updateById(configsUser);
             return AjaxResult.success("更新成功");
         }
     }

     return AjaxResult.error("无效的操作");*/
//    @ApiOperation("我的生成：修改")
//    @PostMapping("/user/edit")
//    @Transactional
//    public AjaxResult edit(@RequestBody ChartConfigsUser configsUser) {
//        if (ObjectUtils.isEmpty(configsUser.getChartName())) {
//            return AjaxResult.error("请填写图表名称");
//        }
//        ChartConfigsUser one = chartConfigsUserService.getOne(new LambdaQueryWrapper<ChartConfigsUser>().
//                eq(ChartConfigsUser::getChartName, configsUser.getChartName())
//                .ne(ChartConfigsUser::getId, configsUser.getId()). //不等于
//                        eq(ChartConfigsUser::getUserId, SecurityUtils.getUserId()).
//                eq(!ObjectUtils.isEmpty(configsUser.getFileId()), ChartConfigsUser::getFileId, configsUser.getFileId()));
//
//        System.out.println(one);
//        if (!ObjectUtils.isEmpty(one)) {
//            return AjaxResult.error("图表名称重复");
//        }
//
//        System.out.println(SecurityUtils.getUserId());
//
//        return AjaxResult.success(chartConfigsUserService.saveOrUpdate(configsUser));
//    }



    @ApiOperation("我的生成：修改")
    @PostMapping("/user/edit")
    @Transactional
    public AjaxResult edit(@RequestBody ChartConfigsUser configsUser) throws UnsupportedEncodingException {
        if (ObjectUtils.isEmpty(configsUser.getChartName())) {
            return AjaxResult.error("请填写图表名称");
        }

        // 检查图表名称是否重复
        ChartConfigsUser one = chartConfigsUserService.getOne(new LambdaQueryWrapper<ChartConfigsUser>()
                .eq(ChartConfigsUser::getChartName, configsUser.getChartName())
                .ne(ChartConfigsUser::getId, configsUser.getId()) // 不等于当前ID
                .eq(ChartConfigsUser::getUserId, SecurityUtils.getUserId())
                .eq(!ObjectUtils.isEmpty(configsUser.getFileId()), ChartConfigsUser::getFileId, configsUser.getFileId()));

        if (!ObjectUtils.isEmpty(one)) {
            return AjaxResult.error("图表名称重复");
        }

        // 处理 chartCover 并生成新的图片文件，更新 imageUrl 字段
        if (!ObjectUtils.isEmpty(configsUser.getChartCover())) {
            String imageUrl = processChartCover(configsUser.getChartCover());
            if (imageUrl == null) {
                return AjaxResult.error("图片处理失败");
            }
            configsUser.setImageUrl(imageUrl);
        }

        // 保存或更新 configsUser 数据
        return AjaxResult.success(chartConfigsUserService.saveOrUpdate(configsUser));
    }


    /**
     * 处理 Base64 编码的图片并保存为文件，返回文件的 URL 路径
     */
    private String processChartCover(String chartCover) {
        // 去除 Base64 前缀
        if (chartCover.startsWith("data:image/png;base64,")) {
            chartCover = chartCover.substring("data:image/png;base64,".length());
        }

        // 检查并解码 Base64 字符串
        byte[] decodedBytes;
        try {
            decodedBytes = Base64.getDecoder().decode(chartCover);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            return null;  // Base64 编码无效
        }

        // 生成随机文件名
        int randomInt = RandomUtils.nextInt(0, 100000);
        String fileName = "chartCover" + randomInt + ".png";
        String urlName = "/static/mychart/" + fileName;
        File file = new File(uploadDir, fileName);

        // 将字节数组写入文件
        try (FileOutputStream fos = new FileOutputStream(file)) {
            fos.write(decodedBytes);
        } catch (IOException e) {
            e.printStackTrace();
            return null;  // 文件保存失败
        }

        return urlName;  // 返回文件的 URL 路径
    }










    public void delectRedisAllkeyByUserId() {
        Long userId = SecurityUtils.getUserId();
        String cacheKeyPattern = CacheConstants.CHART_USER_CONFIGS_KEY + userId + ":*";
        redisCache.deleteObject(cacheKeyPattern);

        try {
            Set<String> keys = redisTemplate.keys(cacheKeyPattern);
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
                logger.info("Cache keys deleted: " + keys);
            } else {
                logger.info("No cache keys found matching pattern: " + cacheKeyPattern);
            }
        } catch (Exception e) {
            logger.error("Error occurred while deleting cache keys: ", e);
        }
    }

/*    @ApiOperation("我的生成：修改")
    @PostMapping("/user/edit")
    @Transactional
    public AjaxResult edit(@RequestBody ChartConfigsUser configsUser) {

        Long userId = SecurityUtils.getUserId();
        // String chartCover = configsUser.getChartCover();
        String chartCover = configsUser.getChartCover();
        // 去除 Base64 前缀
        if (chartCover != null && chartCover.startsWith("data:image/png;base64,")) {
            chartCover = chartCover.substring("data:image/png;base64,".length());
        }
        // 检查并解码 base64 字符串
        byte[] decodedBytes;
        try {
            decodedBytes = Base64.getDecoder().decode(chartCover);
        } catch (IllegalArgumentException e) {
            return AjaxResult.error("Base64编码无效: " + e.getMessage());
        }
        int randomInt = RandomUtils.nextInt(0, 100000);
        String fileName = "chartCover" + randomInt + ".png";
        String urlName = "/static/mychart/" + "chartCover" + randomInt + ".png";
        File file = new File(uploadDir, fileName);
        // 将字节数组写入文件
        try (FileOutputStream fos = new FileOutputStream(file)) {
            fos.write(decodedBytes);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("文件保存失败: " + e.getMessage());
        }
        // 更新 imageUrl 字段
        configsUser.setImageUrl(urlName);

        if (ObjectUtils.isEmpty(configsUser.getChartName())) {
            return AjaxResult.error("请填写图表名称");
        }


        // 检查图表名称是否重复
        ChartConfigsUser one = chartConfigsUserService.getOne(new LambdaQueryWrapper<ChartConfigsUser>()
                .eq(ChartConfigsUser::getChartName, configsUser.getChartName())
                .ne(ChartConfigsUser::getId, configsUser.getId())
                .eq(ChartConfigsUser::getUserId, userId)
                .eq(!ObjectUtils.isEmpty(configsUser.getFileId()), ChartConfigsUser::getFileId, configsUser.getFileId()));

        if (!ObjectUtils.isEmpty(one)) {
            return AjaxResult.error("图表名称重复");
        }

        // 更新图表信息
        boolean isUpdated = chartConfigsUserService.saveOrUpdate(configsUser);
        //操作缓存
        delectRedisAllkeyByUserId();
        if (!isUpdated) {
            return AjaxResult.error("更新失败");
        }


        return AjaxResult.success("更新成功");
    }*/

    @ApiOperation("我的生成：根据id获取单个图表详情")
    @GetMapping("/user/getInfo")
    public AjaxResult getInfo(ChartConfigsUser configsUser) {
        ChartConfigsUser one = chartConfigsUserService.getOne(new LambdaQueryWrapper<ChartConfigsUser>().eq(ChartConfigsUser::getId, configsUser.getId()));
        ChartConfigs configs = chartConfigsService.getById(one.getConfigId());
        one.setTemplateUrl(configs.getTemplateUrl());
        if (!ObjectUtils.isEmpty(one.getTechnologyId())) {
            ChartTechnology technology = chartTechnologyService.getById(one.getTechnologyId());
            one.setTechnologyName(technology.getTechnologyName());
        }
        return AjaxResult.success(one);
    }


    /**
     * 给Ai用
     *
     * @param configsUser
     * @return
     */
    @ApiOperation("我的生成：根据id获取单个图表详情")
    @GetMapping("/user/ai/getInfo")
    public AjaxResult v2getInfo(ChartConfigsUser configsUser) {
        ChartConfigsUser one = chartConfigsUserService.getOne(new LambdaQueryWrapper<ChartConfigsUser>().eq(ChartConfigsUser::getId, configsUser.getId()));
        ChartConfigs configs = chartConfigsService.getById(one.getConfigId());
        one.setTemplateUrl(configs.getTemplateUrl());
        one.setConfigText(configs.getConfigText());
        one.setWindowText(configs.getWindowText());
        if (!ObjectUtils.isEmpty(one.getTechnologyId())) {
            ChartTechnology technology = chartTechnologyService.getById(one.getTechnologyId());
            one.setTechnologyName(technology.getTechnologyName());
        }
        return AjaxResult.success(one);
    }

    /*       @ApiOperation("我的生成：根据id删除（支持批量）")
           @PostMapping("/user/del")
           @Transactional
           public AjaxResult del(@RequestBody ChartConfigsUser configsUser) {

               return AjaxResult.success(chartConfigsUserService.removeByIds(configsUser.getIds()));
           }*/
/*    @ApiOperation("我的生成：根据id删除（支持批量）")
    @PostMapping("/user/del")
    @Transactional
    public AjaxResult del(@RequestBody ChartConfigsUser configsUser) {
        // 先清除缓存
        clearCache(configsUser.getIds());

        // 执行删除操作
        boolean isRemoved = chartConfigsUserService.removeByIds(configsUser.getIds());

        return AjaxResult.success(isRemoved);
    }

    private void clearCache(List<Long> ids) {
        for (Long id : ids) {
            ChartConfigsUser userConfig = chartConfigsUserService.getById(id);
            if (userConfig != null) {
              //  Long userId = userConfig.getUserId();
                Long userId = SecurityUtils.getUserId();
                String cacheKeyPattern = CacheConstants.USER_CHART_CONFIGS_KEY + userId + ":*";
                redisCache.deleteByPattern(cacheKeyPattern);
            } else {
                // 如果 userConfig 为 null，说明数据库中没有这条数据，但是缓存中可能存在
                // 需要清除与用户相关的所有缓存键
                Long userId = SecurityUtils.getUserId();
                String cacheKeyPattern = CacheConstants.USER_CHART_CONFIGS_KEY + userId + ":*";
                redisCache.deleteByPattern(cacheKeyPattern);
            }
        }
    }*/


/*    @ApiOperation("我的生成：根据id删除（支持批量）")
    @PostMapping("/user/del")
    @Transactional
    public AjaxResult del(@RequestBody ChartConfigsUser configsUser) {
        // 执行删除操作
        boolean isRemoved = chartConfigsUserService.removeByIds(configsUser.getIds());

        // 如果删除成功，清除缓存
        if (isRemoved) {
            Long userId = SecurityUtils.getUserId();
            String cacheKeyPattern = CacheConstants.CHART_USER_CONFIGS_KEY + userId + ":*";
            redisCache.deleteObject(cacheKeyPattern);
            logger.info("删除缓存的key是: " + cacheKeyPattern);
        }

        return AjaxResult.success(isRemoved);
    }*/


    // 你的删除方法
    @ApiOperation("我的生成：根据id删除（支持批量）")
    @PostMapping("/user/del")
    @Transactional
    public AjaxResult del(@RequestBody ChartConfigsUser configsUser) {
        // 执行删除操作
        boolean isRemoved = chartConfigsUserService.removeByIds(configsUser.getIds());

        // 如果删除成功，清除缓存
        if (isRemoved) {
            Long userId = SecurityUtils.getUserId();
            String cacheKeyPattern = CacheConstants.CHART_USER_CONFIGS_KEY + userId + ":*";
            logger.info("Attempting to delete cache with pattern: " + cacheKeyPattern);

            try {
                Set<String> keys = redisTemplate.keys(cacheKeyPattern);
                if (keys != null && !keys.isEmpty()) {
                    redisTemplate.delete(keys);
                    logger.info("Cache keys deleted: " + keys);
                } else {
                    logger.info("No cache keys found matching pattern: " + cacheKeyPattern);
                }
            } catch (Exception e) {
                logger.error("Error occurred while deleting cache keys: ", e);
            }
        }
        return AjaxResult.success(isRemoved);
    }


    @ApiOperation("图表类型列表")
    @GetMapping("/type/list")
    @Transactional
    public AjaxResult typeList() {
        ChartType list = redisCache.getCacheObject(CacheConstants.CHART_TYPE);
        return AjaxResult.success(list);
    }


    @ApiOperation("获取操作权限")
    @GetMapping("/getoperPower")
    @Transactional
    public AjaxResult getoperPower(Integer isFree) {
        //判断图表是否免费
        if (isFree == 0) {
            return AjaxResult.success(WeChatConstants.OK);
        } else {
            if (SecurityUtils.isAdmin()) {
                return AjaxResult.success(WeChatConstants.OK);
            } else if (SecurityUtils.isVip()) {
                return AjaxResult.success(WeChatConstants.OK);
            } else {
                Long userId = SecurityUtils.getUserId();
                SysUser user = userService.getById(userId);

                if (!ObjectUtils.isEmpty(user.getOpenId())) {
                    if (!ObjectUtils.isEmpty(user.getIsSubscribe())) {
                        Integer freeOper = user.getFreeOper();
                        if (freeOper == 0 && ObjectUtils.isEmpty(user.getEmail())) {
                            //完善信息
                            return AjaxResult.success(WeChatConstants.IMPROVE_INFORMATION);
                        } else if (freeOper == 0 && !ObjectUtils.isEmpty(user.getEmail()) && user.getIsForward() == 0) {
                            //转发推文
                            return AjaxResult.success(WeChatConstants.FORWARD_TWEETS);
                        } else if (freeOper == 0 && user.getIsForward() == 1) {
                            //开通vip
                            return AjaxResult.success(WeChatConstants.AC_VIP);
                        } else if (freeOper > 0) {
                            freeOper = freeOper - 1;
                            user.setFreeOper(freeOper);
                            boolean result = userService.saveOrUpdate(user);
                            if (result) {
                                return AjaxResult.success(freeOper);
                            }
                        }
                    } else {
                        //关注微信公众号
                        return AjaxResult.success(WeChatConstants.FOLLOW_WECHAT_OFFICIAL_ACCOUNT);
                    }
                } else {
                    //绑定微信
                    return AjaxResult.success(WeChatConstants.BIND_WECHAT);
                }
            }
        }
        return AjaxResult.error();
    }


    @ApiOperation("通过转发获取操作次数")
    @GetMapping("/getoperByforward")
    @Transactional
    public AjaxResult getoperByforward() {
        Long userId = SecurityUtils.getUserId();
        SysUser user = userService.getById(userId);
        if (!ObjectUtils.isEmpty(user.getIsSubscribe())) {
            if (user.getIsForward() == 0) {
                Integer freeOper = user.getFreeOper();
                user.setFreeOper(freeOper + 3);
                user.setIsForward(1);
                boolean result = userService.saveOrUpdate(user);
                if (result) {
                    return AjaxResult.success("转发成功，已经获得3次免费导出");
                }
            } else {
                //该账号已经进行转发，无法再次获得操作次数
                return AjaxResult.success("转发成功（只有第一次转发才可获取免费导出）");
            }
        }
        //关注微信公众号
        return AjaxResult.success(WeChatConstants.FOLLOW_WECHAT_OFFICIAL_ACCOUNT);
    }


    @ApiOperation("保存用户操作记录")
    @PostMapping("/oper/save")
    @Transactional
    public AjaxResult oper(@RequestBody ChartStatistics chartStatistics) {
        chartStatistics.setUserId(SecurityUtils.getUserId());
        boolean save = statisticsService.save(chartStatistics);
        if (save) {
            return AjaxResult.success();
        }
        return AjaxResult.error();
    }


    @ApiOperation("获取图表数据上传地址")
    @GetMapping("/getDataAddr")
    @Transactional
    public AjaxResult getInterface(Long configId) {
        return AjaxResult.success(
                redisCache.getCacheObject(CHART_INTERFACE + configId));
    }

    /**
     * new
     *
     * @param configId
     * @return
     */
    @ApiOperation("获取图表数据上传地址")
    @GetMapping("/chartDataAddress")
    @Transactional
    public AjaxResult getChartDataAddress(Long configId) {
        return AjaxResult.success(
                redisCache.getCacheObject(CHART_INTERFACE + configId));
    }


    @ApiOperation("保存用户点击‘我知道了’操作记录")
    @PostMapping("/oper/notice")
    @Transactional
    public AjaxResult notice() {
        if (SecurityUtils.isNoticed()) {
            return AjaxResult.success();
        }
        SysUser sysUser = new SysUser();
        sysUser.setFirstNotice(1);
        sysUser.setUserId(SecurityUtils.getUserId());
        boolean save = userService.saveOrUpdate(sysUser);
        if (save) {
            refreshToken();
            return AjaxResult.success();
        }
        return AjaxResult.error();
    }


    //将主题、技术领域、图表类型、图表接口等信息进行缓存
    @PostConstruct  //Spring Boot 应用程序启动时，通过 @PostConstruct 注解在应用初始化后执行一个方法
    private void extracted() {
        List<ChartTheme> list = themeService.list(new LambdaQueryWrapper<ChartTheme>().orderByAsc(ChartTheme::getThemeType).orderByAsc(ChartTheme::getSort));
//        Map<Integer, List<ChartTheme>> map = list.stream().collect(Collectors.groupingBy(ChartTheme::getThemeType));
//        map.forEach((key,value)->{
//            redisCache.setCacheObject(CacheConstants.CHART_THEME+key,map.get(key));
//        });
        redisCache.setCacheObject(CHART_THEME, list);
        list.stream().forEach(e -> {
            redisCache.setCacheObject(CHART_THEME + e.getId(), e);
        });

        List<ChartTechnology> technologyList = chartTechnologyService.list(new LambdaQueryWrapper<ChartTechnology>().eq(ChartTechnology::getParentId, 0));
        for (int i = 0; i < technologyList.size(); i++) {
            ChartTechnology chartTechnology1 = technologyList.get(i);
            List<ChartTechnology> list1 = chartTechnologyService.list(new LambdaQueryWrapper<ChartTechnology>().eq(ChartTechnology::getParentId, chartTechnology1.getId()));
            chartTechnology1.setChildren(list1);
        }
        redisCache.setCacheObject(CacheConstants.CHART_TECHNOLOGY, technologyList);
        System.out.println("---------------------------------------------------------在以下修改---------------------------------------------");
        // 获取父级 ChartSubjectType 列表
        List<ChartSubjectType> chartSubjectTypeList = chartSubjectTypeService.list(new LambdaQueryWrapper<ChartSubjectType>().eq(ChartSubjectType::getParentId, 0));
        // 为每个父级 ChartSubjectType 设置子级列表
        for (int i = 0; i < chartSubjectTypeList.size(); i++) {
            ChartSubjectType chartSubjectType = chartSubjectTypeList.get(i);
            List<ChartSubjectType> list2 = chartSubjectTypeService.list(new LambdaQueryWrapper<ChartSubjectType>().eq(ChartSubjectType::getParentId, chartSubjectType.getId()));
            chartSubjectType.setChildren(list2);
        }
        // 将 ChartSubjectType 列表缓存到 Redis
        redisCache.setCacheObject(CacheConstants.CHART_SUBJECT_TYPE, chartSubjectTypeList);
        System.out.println("---------------------------------------------------------------在以上修改---------------------------------------");
        List<ChartType> typeList = chartTypeService.list(new LambdaQueryWrapper<ChartType>().orderByAsc(ChartType::getSort));
        redisCache.setCacheObject(CacheConstants.CHART_TYPE, typeList);

        List<ChartConfigsInterface> faces = chartConfigsService.getChartInterfaces();
        faces.forEach(e -> {
            String configAddr = e.getConfigAddr();
            if (!ObjectUtils.isEmpty(configAddr)) {
                redisCache.setCacheObject(CHART_INTERFACE + e.getConfigId(), configAddr);
            }
        });
    }

    /**
     * 查询用户保存到我的生成的数量
     *
     * @return
     */
    @GetMapping("queryChartCountById")
    public AjaxResult queryChartCountById() {
        Long chartNumber = chartConfigsService.queryChartCountById();
        return AjaxResult.success(chartNumber);
    }





/*    //将主题、技术领域、图表类型、图表接口等信息进行缓存
    @PostConstruct
    private void extracteds() {
        List<ChartTheme> list = themeService.list(new LambdaQueryWrapper<ChartTheme>().orderByAsc(ChartTheme::getThemeType).orderByAsc(ChartTheme::getSort));
//        Map<Integer, List<ChartTheme>> map = list.stream().collect(Collectors.groupingBy(ChartTheme::getThemeType));
//        map.forEach((key,value)->{
//            redisCache.setCacheObject(CacheConstants.CHART_THEME+key,map.get(key));
//        });
        redisCache.setCacheObject(CacheConstants.CHART_THEME,list);
        list.stream().forEach(e->{
            redisCache.setCacheObject(CacheConstants.CHART_THEME+e.getId(),e);
        });



        List<ChartTechnology> technologyList = chartTechnologyService.list(new LambdaQueryWrapper<ChartTechnology>().eq(ChartTechnology::getParentId, 0));
        for (int i = 0; i < technologyList.size(); i++) {
            ChartTechnology chartTechnology1 = technologyList.get(i);
            List<ChartTechnology> list1 = chartTechnologyService.list(new LambdaQueryWrapper<ChartTechnology>().eq(ChartTechnology::getParentId, chartTechnology1.getId()));
            chartTechnology1.setChildren(list1);
        }
        redisCache.setCacheObject(CacheConstants.CHART_TECHNOLOGY,technologyList);


        List<ChartType> typeList = chartTypeService.list(new LambdaQueryWrapper<ChartType>().orderByAsc(ChartType::getSort));
        redisCache.setCacheObject(CacheConstants.CHART_TYPE,typeList);

        List<ChartConfigsInterface> faces=chartConfigsService.getChartInterfaces();
        faces.forEach(e->{
            String configAddr = e.getConfigAddr();
            if (!ObjectUtils.isEmpty(configAddr)) {
                redisCache.setCacheObject(CHART_INTERFACE+e.getConfigId(),configAddr);
            }
        });
    }*/

    /**
     * 刷新令牌有效期
     */
    public void refreshToken() {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();

        user.setFirstNotice(1);

        // 根据uuid将loginUser缓存
        String userKey = tokenService.getTokenKey1(loginUser.getToken());

        redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
    }


}
